﻿using System;
using System.IO;
using System.Threading;

namespace ConsoleGame1
{
    class Champion
    {
        private char letter;
        public Champion(char ch)
        {
            this.letter = ch;
        }
        public char Letter
        {
            get
            {
                return this.letter;
            }
        }
    }
    class ConsoleGame1
    {
        //Global vars.
        static int playerX = 12;
        static int playerY = 0;
        static int platformHoleLenght = 10;
        static Random rdm = new Random();
        static ConsoleKeyInfo input;
        static int score = 0;
        static int bonusLives = 0;
        static int bonusCount = 0;
        static int addToScore = 0;
        static double balanceLives = 0;
        static Champion champ;

        //Vars for first platform.
        static int firstPlatformX = 0;
        static int firstPlatformY = 29;
        static int moveUpFirstPlatform = 0;
        static int firstPlatformHoleX = rdm.Next(10, 26); //This number shows where the hole begins at the X + the lenght of the hole, wich is 10.

        //Vars for second platform.
        static int secondPlatformX = 0;
        static int secondPlatformY = 29;
        static int moveUpSecondPlatform = 15;
        static int secondPlatformHoleX = rdm.Next(10, 26);

        static void DisableCursorGetRidOfScrollBarsAndSetWindowSize()
        {
            //Disable cursor.
            Console.CursorVisible = false;
            Console.SetWindowSize(25, 30);

            //DisableScrollBars.
            Console.BufferWidth = Console.WindowWidth;
            Console.BufferHeight = Console.WindowHeight;
        }

        static void HighScoreWrite()
        {
            try
            {
                StreamReader highScoreRead = new StreamReader("highscorefile.txt");
                string currentHighScore = highScoreRead.ReadLine();
                int currentHighScoreInt = int.Parse(currentHighScore);
                highScoreRead.Close();

                if (currentHighScoreInt < score)
                {
                    StreamWriter highScoreWrite = new StreamWriter("highscorefile.txt");
                    using (highScoreWrite)
                    {
                        highScoreWrite.WriteLine(score);
                    }
                }
                HighScoreWriteOnScreen();
            }
            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (IOException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (FormatException)
            {
                Console.WriteLine();
                Console.WriteLine("The Highscorefile.txt might be empty or the input is not i a correct format!");
                Console.WriteLine();
            }

        }
        private static void AddBonusLives()
        {
            if (bonusCount % 8 == 0 && moveUpFirstPlatform == 29)
            {
                bonusLives++;
            }
        }
        static void CollisionDetect()
        {
            int escPressed = 0;
            int IsQPressed = 0;

            //Find second platforms hole!
            if (!(moveUpSecondPlatform < 29) && !(playerX > Console.WindowWidth - secondPlatformHoleX && playerX < Console.WindowWidth - secondPlatformHoleX + 10))
            {
                if (bonusLives == 0)
                {
                    //Resize window for Menu sign
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.Clear();
                    Console.Beep();
                    Console.SetWindowSize(60, 25);
                    PrintGameOverSign();

                    Console.WriteLine();
                    Console.WriteLine("Game Over Press Esc");
                    Console.WriteLine("to play again.");
                    Console.Write("Your score is : ");
                    Console.WriteLine(score);

                    //Save the high score in the highscorefile.txt
                    HighScoreWrite();
                    Console.WriteLine("To Delete high score press Q!");
                    while (true)
                    {
                        escPressed = CheckForPressedEsc(escPressed);
                        IsQPressed = IsQPressedCheck(IsQPressed);
                        if (escPressed == 1)
                        {
                            score = 0;
                            return;
                        }
                        if (IsQPressed == 1)
                        {
                            score = 0;

                            //Delete High Score.
                            DeleteHighScore();
                            Console.WriteLine("High Score Set to 0");
                            Thread.Sleep(500);
                            return;
                        }
                    }
                }
                else
                {
                    bonusLives--;
                }
            }

            //Find first platforms hole!
            if (!(moveUpFirstPlatform < 29) && !(playerX > Console.WindowWidth - firstPlatformHoleX && playerX < Console.WindowWidth - firstPlatformHoleX + 10))
            {
                if (bonusLives == 0)
                {
                    //Resize window for Menu sign
                    Console.Clear();
                    Console.Beep();
                    Console.SetWindowSize(60, 25);
                    PrintGameOverSign();

                    Console.WriteLine();
                    Console.WriteLine("Game Over Press Esc");
                    Console.WriteLine("to play again.");
                    Console.Write("Your score is : ");
                    Console.WriteLine(score);

                    //Save the high score in the highscorefile.txt
                    HighScoreWrite();
                    Console.WriteLine("To Delete high score press Q!");

                    while (true)
                    {
                        escPressed = CheckForPressedEsc(escPressed);
                        IsQPressed = IsQPressedCheck(IsQPressed);
                        if (escPressed == 1)
                        {
                            score = 0;
                            return;
                        }
                        if (IsQPressed == 1)
                        {
                            score = 0;

                            //Delete high score.
                            DeleteHighScore();
                            Console.WriteLine("High Score Set to 0");
                            Thread.Sleep(500);
                            return;
                        }
                    }
                }
                else
                {
                    bonusLives--;
                }
            }
        }

        private static void DeleteHighScore()
        {
            try
            {
                //Write a 0 in the highscorefile.txt
                using (StreamWriter write = new StreamWriter("highscorefile.txt"))
                {
                    write.WriteLine("0");
                }
            }

            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (IOException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (FormatException)
            {
                Console.WriteLine();
                Console.WriteLine("The Highscorefile.txt might be empty or the input is not i a correct format!");
                Console.WriteLine();
            }
        }

        private static void HighScoreWriteOnScreen()
        {
            try
            {
                using (StreamReader read = new StreamReader("highscorefile.txt"))
                {
                    Console.WriteLine("Your High Score is {0} ", read.ReadLine());
                }
            }

            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (IOException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (FormatException)
            {
                Console.WriteLine();
                Console.WriteLine("The Highscorefile.txt might be empty or the input is not i a correct format!");
                Console.WriteLine();
            }

        }

        private static void PrintGameOverSign()
        {
            string[,] G = new string[,]
         {
             { "#", "#", "#", "#", "#" },
             { "#", " ", " ", " ", " " },
             { "#", " ", "#", "#", "#" },
             { "#", " ", " ", " ", "#" },
             { "#", "#", "#", "#", "#" },
         };

            string[,] A = new string[,]
         {
             { " ", " ", "#", " ", " " },
             { " ", "#", " ", "#", " " },
             { "#", " ", " ", " ", "#" },
             { "#", "#", "#", "#", "#" },
             { "#", " ", " ", " ", "#" },
         };

            string[,] M = new string[,]
         {
            { " ", "#", " ", "#", " " },
            { "#", "#", "#", "#", "#" },
            { "#", " ", "#", " ", "#" },
            { "#", " ", "#", " ", "#" },
            { "#", " ", " ", " ", "#" },
         };

            string[,] E = new string[,]
         {
            { "#", "#", "#", "#", "#" },
            { "#", " ", " ", " ", " " },
            { "#", "#", "#", "#", " " },
            { "#", " ", " ", " ", " " },
            { "#", "#", "#", "#", "#" },
         };

            string[,] O = new string[,]
         {
            { "#", "#", "#", "#", "#" },
            { "#", " ", " ", " ", "#" },
            { "#", " ", " ", " ", "#" },
            { "#", " ", " ", " ", "#" },
            { "#", "#", "#", "#", "#" },
         };

            string[,] V = new string[,]
         {
            { "#", " ", " ", " ", "#" },
            { "#", "#", " ", "#", "#" },
            { "#", "#", " ", "#", "#" },
            { " ", "#", "#", "#", " " },
            { " ", " ", "#", "", " " },
         };

            string[,] R = new string[,]
          {
            { "#", "#", "#", "#", "#" },
            { "#", " ", " ", " ", "#" },
            { "#", "#", "#", "#", "#" },
            { "#", " ", "#", " ", " " },
            { "#", " ", " ", "#", "#" },
         };
            PrintArray(G, 0, 0);
            PrintArray(A, 8, 0);
            PrintArray(M, 16, 0);
            PrintArray(E, 24, 0);
            Console.WriteLine();
            PrintArray(O, 0, 7);
            PrintArray(V, 8, 7);
            PrintArray(E, 16, 7);
            PrintArray(R, 24, 7);
        }

        static void PrintArray(string[,] array, int cursurPositionAtCow, int curstorPositionAtRow)
        {
            for (int row = 0; row < array.GetLength(0); row++)
            {
                for (int col = 0; col < array.GetLength(1); col++)
                {
                    Console.SetCursorPosition(cursurPositionAtCow + col, curstorPositionAtRow + row);
                    Console.Write("{0} ", array[row, col]);
                }
                Console.WriteLine();
            }
        }

        private static int IsQPressedCheck(int isQPressed)
        {
            if (Console.KeyAvailable)
            {
                ConsoleKeyInfo Q = Console.ReadKey();

                if (Q.Key == ConsoleKey.Q)
                {
                    return isQPressed = 1;
                }
            }
            return isQPressed = 0;
        }

        private static int CheckForPressedEsc(int isEscPressed)
        {
            if (Console.KeyAvailable)
            {
                ConsoleKeyInfo esc = Console.ReadKey();

                if (esc.Key == ConsoleKey.Escape)
                {
                    return isEscPressed = 1;
                }
            }
            return isEscPressed = 0;
        }
        private static int ChooseLevel()
        {
            Console.WriteLine("Choose level: ");
            Console.WriteLine("1. Easy");
            Console.WriteLine("2. Normal");
            Console.WriteLine("3. Hard");
            return int.Parse(Console.ReadLine());
        }
        private static char ChooseChampion()
        {
            Console.WriteLine("Choose champion: ");
            Console.WriteLine("1. @");
            Console.WriteLine("2. #");
            Console.WriteLine("3. $");
            string champ = Console.ReadLine();
            switch (champ)
            {
                case "1":
                    champ = "@";
                    break;
                case "2":
                    champ = "#";
                    break;
                case "3":
                    champ = "$";
                    break;
                default:
                    throw new ArgumentException();
            }
            return char.Parse(champ);
        }
        static void Main()
        {
            Console.WriteLine("Game menu");
            while (true)
            {
                Console.WriteLine("Press 1 to play.");
                Console.WriteLine("Press 2 to view highscore.");
                Console.WriteLine("Press 3 to delete highscore.");
                int choice = int.Parse(Console.ReadLine());

                //Menu options
                if (choice == 1)
                {
                    Console.Clear();
                    int level = ChooseLevel();
                    int sleep = 0;
                    if (level == 1)
                    {
                        sleep = 50;
                        addToScore = 1;
                        balanceLives = 1;
                    }
                    else if (level == 2)
                    {
                        sleep = 10;
                        addToScore = 2;
                        balanceLives = 1.5;
                    }
                    else
                    {
                        sleep = -65;
                        addToScore = 3;
                        balanceLives = 2;
                    }
                    char letter = ChooseChampion();
                    champ = new Champion(letter);
                    Thread.Sleep(120 + sleep);
                    Console.WriteLine("Get Ready!!");


                    while (true)
                    {
                        DisableCursorGetRidOfScrollBarsAndSetWindowSize();
                        AddBonusLives();
                        Draw();
                        MoveLogic();
                        CollisionDetect();

                        bonusCount++;
                        Console.SetCursorPosition(0, 29);
                        Console.Write("Score : {0}  lives: {1}", score, bonusLives);
                        //Console.SetCursorPosition(11, 29);
                        // Console.Write("highScore : {0} ", bonusLives);
                        Thread.Sleep(120 + sleep);
                        Console.Clear();
                    }
                }
                else if (choice == 2)
                {
                    try
                    {
                        using (StreamReader highScoreRead = new StreamReader("highscorefile.txt"))
                        {
                            Console.WriteLine();
                            Console.Write("Highscore is :");
                            Console.WriteLine(highScoreRead.ReadLine());
                            Console.WriteLine();
                        }
                    }
                    catch (FileNotFoundException e)
                    {
                        Console.WriteLine(e.Message);
                    }

                    catch (DirectoryNotFoundException e)
                    {
                        Console.WriteLine(e.Message);
                    }

                    catch (IOException e)
                    {
                        Console.WriteLine(e.Message);
                    }

                    catch (UnauthorizedAccessException e)
                    {
                        Console.WriteLine(e.Message);
                    }

                    catch (FormatException)
                    {
                        Console.WriteLine();
                        Console.WriteLine("The Highscorefile.txt might be empty or the input is not i a correct format!");
                        Console.WriteLine();
                    }
                }
                else if (choice == 3)
                {
                    DeleteHighScore();
                    Console.WriteLine();
                    Console.WriteLine("Highscore deleted!");
                }
                else
                {
                    Console.WriteLine("Sorry wrong command!");
                }
            }
        }

        private static void MoveLogic()
        {
            if (Console.KeyAvailable)
            {
                input = Console.ReadKey();
                while (Console.KeyAvailable)
                {
                    Console.ReadKey(true);
                }

                if (input.Key == ConsoleKey.RightArrow)
                {
                    CheckOutOfBound();
                    playerX++;
                }
                if (input.Key == ConsoleKey.LeftArrow)
                {
                    CheckOutOfBound();
                    playerX--;
                }
            }
        }

        private static void Draw()
        {
            //Console.ForegroundColor = ConsoleColor.White;
            DrawPlayer();
            DrawPlatform();
            DrawPlatformTwo();
        }

        private static void DrawPlatform()
        {
            //Restart once we hit the top.
            if (moveUpFirstPlatform == 29)
            {
                moveUpFirstPlatform = 0;
                //Generate new rdm number after every refresh to change the hole position.
                firstPlatformHoleX = rdm.Next(10, 26);
                score += addToScore;
            }

            Console.SetCursorPosition(firstPlatformX, firstPlatformY - moveUpFirstPlatform);
            //Draw one line.
            if (score % 16 == 0)
            {
                ChangeTextColor();
            }
            Console.Write(new string('_', Console.WindowWidth - firstPlatformHoleX));
            Console.Write(new string(' ', platformHoleLenght));
            Console.Write(new string('_', firstPlatformHoleX - platformHoleLenght));
            moveUpFirstPlatform++;

        }

        private static void DrawPlatformTwo()
        {
            //Restart once we hit the top.
            if (moveUpSecondPlatform == 29)
            {
                moveUpSecondPlatform = 0;
                //Generate new rdm number after every refresh to change the hole position.
                secondPlatformHoleX = rdm.Next(10, 26);
                score += addToScore;
            }

            Console.SetCursorPosition(secondPlatformX, secondPlatformY - moveUpSecondPlatform);
            // Draw one line.
            if (score % 16 == 0)
            {
                ChangeTextColor();
            }
            Console.Write(new string('_', Console.WindowWidth - secondPlatformHoleX));
            Console.Write(new string(' ', platformHoleLenght));
            Console.Write(new string('_', secondPlatformHoleX - platformHoleLenght));
            moveUpSecondPlatform++;

        }
        private static void ChangeTextColor()
        {
            Random rnd = new Random();
            int randomColor = rdm.Next(1, 8);
            switch (randomColor)
            {
                case 1:
                    Console.ForegroundColor = ConsoleColor.White;
                    break;
                case 2:
                    Console.ForegroundColor = ConsoleColor.Blue;
                    break;
                case 3:
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    break;
                case 4:
                    Console.ForegroundColor = ConsoleColor.Gray;
                    break;
                case 5:
                    Console.ForegroundColor = ConsoleColor.Green;
                    break;
                case 6:
                    Console.ForegroundColor = ConsoleColor.Magenta;
                    break;
                case 7:
                    Console.ForegroundColor = ConsoleColor.Red;
                    break;
                case 8:
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    break;
                default: throw new IndexOutOfRangeException();
            }
        }
        private static void CheckOutOfBound()
        {
            if (playerX == 0)
            {
                playerX++;
            }
            else if (playerX == Console.WindowWidth - 1)
            {
                playerX--;
            }
        }

        private static void DrawPlayer()
        {
            Console.SetCursorPosition(playerX, playerY);
            Console.Write(champ.Letter);
        }

    }
}


